home *** CD-ROM | disk | FTP | other *** search
- Path: uunet!bbn.com!rsalz
- From: rsalz@uunet.uu.net (Rich Salz)
- Newsgroups: comp.sources.unix
- Subject: v18i077: MIT Athena delete/undelete programs, Part05/06
- Message-ID: <1637@fig.bbn.com>
- Date: 29 Mar 89 04:33:15 GMT
- Lines: 598
- Approved: rsalz@uunet.UU.NET
-
- Submitted-by: Jonathan I. Kamens <jik@PIT-MANAGER.MIT.EDU>
- Posting-number: Volume 18, Issue 77
- Archive-name: undel/part05
-
- #! /bin/sh
- # This is a shell archive. Remove anything before this line, then unpack
- # it by saving it into a file and typing "sh file". To overwrite existing
- # files, type "sh file -c". You can also feed this as standard input via
- # unshar, or by typing "sh <file", e.g.. If this archive is complete, you
- # will see the following message at the end:
- # "End of archive 5 (of 6)."
- # Contents: undelete.c
- # Wrapped by jik@pit-manager on Mon Mar 27 12:16:54 1989
- PATH=/bin:/usr/bin:/usr/ucb ; export PATH
- if test -f 'undelete.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'undelete.c'\"
- else
- echo shar: Extracting \"'undelete.c'\" \(12143 characters\)
- sed "s/^X//" >'undelete.c' <<'END_OF_FILE'
- X/*
- X * $Source: /mit/jik/src/delete/RCS/undelete.c,v $
- X * $Author: jik $
- X *
- X * This program is part of a package including delete, undelete,
- X * lsdel, expunge and purge. The software suite is meant as a
- X * replacement for rm which allows for file recovery.
- X *
- X * Copyright (c) 1989 by the Massachusetts Institute of Technology.
- X * For copying and distribution information, see the file "mit-copyright.h."
- X */
- X
- X#if (!defined(lint) && !defined(SABER))
- X static char rcsid_undelete_c[] = "$Header: undelete.c,v 1.15 89/03/27 12:08:08 jik Exp $";
- X#endif
- X
- X#include <stdio.h>
- X#include <sys/types.h>
- X#include <sys/dir.h>
- X#include <sys/param.h>
- X#include <strings.h>
- X#include <sys/stat.h>
- X#include "directories.h"
- X#include "pattern.h"
- X#include "util.h"
- X#include "undelete.h"
- X#include "mit-copyright.h"
- X
- X#define ERROR_MASK 1
- X#define NO_DELETE_MASK 2
- X
- Xchar *malloc(), *realloc();
- X
- Xint interactive, recursive, verbose, directoriesonly, noop, force;
- Xint del_recursive = 0; /* this tells the pattern matcher that we do */
- X /* *not* want it to recurse deleted directories */
- X /* when recursive is set to false. */
- X
- Xchar *whoami, *error_buf;
- X
- X
- X
- X
- Xmain(argc, argv)
- Xint argc;
- Xchar *argv[];
- X{
- X extern char *optarg;
- X extern int optind;
- X int arg;
- X int status = 0;
- X
- X whoami = lastpart(argv[0]);
- X interactive = recursive = verbose = directoriesonly = noop = force = 0;
- X error_buf = malloc(MAXPATHLEN + strlen(whoami));
- X if (! error_buf) {
- X perror(whoami);
- X exit(1);
- X }
- X while ((arg = getopt(argc, argv, "firvnR")) != -1) {
- X switch (arg) {
- X case 'f':
- X force++;
- X break;
- X case 'i':
- X interactive++;
- X break;
- X case 'r':
- X recursive++;
- X if (directoriesonly) {
- X fprintf(stderr, "%s: -r and -R and mutually exclusive.\n",
- X whoami);
- X usage();
- X exit(1);
- X }
- X break;
- X case 'v':
- X verbose++;
- X break;
- X case 'n':
- X noop++;
- X break;
- X case 'R':
- X directoriesonly++;
- X if (recursive) {
- X fprintf(stderr, "%s: -r and -R are mutually exclusive.\n",
- X whoami);
- X usage();
- X exit(1);
- X }
- X default:
- X usage();
- X exit(1);
- X }
- X }
- X if (optind == argc)
- X exit(interactive_mode());
- X else while (optind < argc) {
- X status = status | undelete(argv[optind]);
- X optind++;
- X }
- X exit(status & ERROR_MASK);
- X}
- X
- X
- X
- Xinteractive_mode()
- X{
- X char buf[MAXPATHLEN];
- X char *ptr;
- X int status = 0;
- X
- X if (verbose) {
- X printf("Enter the files to be undeleted, one file per line.\n");
- X printf("Hit <RETURN> on a line by itself to exit.\n\n");
- X }
- X do {
- X printf("%s: ", whoami);
- X ptr = fgets(buf, MAXPATHLEN, stdin);
- X if (! ptr) {
- X printf("\n");
- X return(status);
- X }
- X ptr = index(buf, '\n'); /* fgets breakage */
- X if (ptr)
- X *ptr = '\0';
- X if (! *buf)
- X return(status);
- X status = status | undelete(buf);
- X } while (*ptr);
- X return(status);
- X}
- X
- X
- X
- Xusage()
- X{
- X fprintf(stderr, "Usage: %s [ options ] [filename ...]\n", whoami);
- X fprintf(stderr, "Options are:\n");
- X fprintf(stderr, " -r recursive\n");
- X fprintf(stderr, " -i interactive\n");
- X fprintf(stderr, " -f force\n");
- X fprintf(stderr, " -v verbose\n");
- X fprintf(stderr, " -n noop\n");
- X fprintf(stderr, " -R directories only (i.e. no recursion)\n");
- X fprintf(stderr, " -- end options and start filenames\n");
- X fprintf(stderr, "-r and -D are mutually exclusive\n");
- X}
- X
- X
- Xundelete(file_exp)
- Xchar *file_exp;
- X{
- X char *file_re;
- X char **found_files;
- X int num_found;
- X char *startdir;
- X int status = 0;
- X filerec *current;
- X
- X if (*file_exp == '/') {
- X startdir = "/";
- X file_re = parse_pattern(file_exp + 1);
- X }
- X else {
- X startdir = "";
- X file_re = parse_pattern(file_exp);
- X }
- X if (! file_re)
- X return(ERROR_MASK);
- X found_files = get_the_files(startdir, file_re, &num_found);
- X free(file_re);
- X if (num_found) {
- X process_files(found_files, num_found);
- X if (*file_exp == '/')
- X current = get_root_tree();
- X else
- X current = get_cwd_tree();
- X status = recurs_and_undelete(current);
- X }
- X else {
- X if (! force)
- X fprintf(stderr, "%s: %s not found\n", whoami, file_exp);
- X status = ERROR_MASK;
- X }
- X return(status);
- X}
- X
- X
- X
- X
- X
- Xrecurs_and_undelete(leaf)
- Xfilerec *leaf;
- X{
- X int status = 0;
- X
- X if ((leaf->specified) && ((leaf->specs.st_mode & S_IFMT) == S_IFDIR))
- X status = do_directory_undelete(leaf);
- X /* the "do_directory_undelete" really only asks the user if he */
- X /* wants to expunge the directory, it doesn't do any deleting. */
- X if (! status) {
- X if (leaf->dirs)
- X status |= recurs_and_undelete(leaf->dirs);
- X if (leaf->files)
- X status |= recurs_and_undelete(leaf->files);
- X }
- X if (leaf->specified)
- X status |= do_undelete(leaf);
- X if (leaf->next)
- X status |= recurs_and_undelete(leaf->next);
- X free_leaf(leaf);
- X return(status);
- X}
- X
- X
- X
- X
- X
- X
- Xdo_directory_undelete(file_ent)
- Xfilerec *file_ent;
- X{
- X char buf[MAXPATHLEN];
- X
- X get_leaf_path(file_ent, buf);
- X convert_to_user_name(buf, buf);
- X
- X if (interactive) {
- X printf("%s: Undelete directory %s? ", whoami, buf);
- X if (! yes())
- X return(NO_DELETE_MASK);
- X }
- X return(0);
- X}
- X
- X
- X
- X
- X
- Xprocess_files(files, num)
- Xchar **files;
- Xint num;
- X{
- X int i;
- X listrec *new_files;
- X listrec *filelist;
- X
- X filelist = (listrec *) malloc(sizeof(listrec) * num);
- X if (! filelist) {
- X perror(sprintf(error_buf, "%s: process_files\n", whoami));
- X exit(1);
- X }
- X for (i = 0; i < num; i++) {
- X filelist[i].real_name = malloc(strlen(files[i]) + 1);
- X strcpy(filelist[i].real_name, files[i]);
- X filelist[i].user_name = malloc(strlen(files[i]) + 1);
- X convert_to_user_name(files[i], filelist[i].user_name);
- X free(files[i]);
- X }
- X free(files);
- X
- X new_files = sort_files(filelist, num);
- X new_files = unique(new_files, &num);
- X if (initialize_tree()) {
- X exit(1);
- X }
- X for (i = 0; i < num; i++) {
- X if (!add_path_to_tree(new_files[i].real_name)) {
- X fprintf(stderr, "%s: error adding path to filename tree\n",
- X whoami);
- X exit(1);
- X }
- X else {
- X free(new_files[i].real_name);
- X free(new_files[i].user_name);
- X }
- X }
- X free(new_files);
- X return(0);
- X}
- X
- X
- X
- X
- X
- X
- X
- X
- Xdo_undelete(file_ent)
- Xfilerec *file_ent;
- X{
- X struct stat stat_buf;
- X char user_name[MAXPATHLEN], real_name[MAXPATHLEN];
- X
- X get_leaf_path(file_ent, real_name);
- X convert_to_user_name(real_name, user_name);
- X
- X if (interactive) {
- X if ((file_ent->specs.st_mode & S_IFMT) == S_IFDIR)
- X printf("%s: Undelete directory %s? ", whoami, user_name);
- X else
- X printf("%s: Undelete %s? ", whoami, user_name);
- X if (! yes())
- X return(NO_DELETE_MASK);
- X }
- X if (! lstat(user_name, &stat_buf)) if (! force) {
- X printf("%s: An undeleted %s already exists.\n", whoami, user_name);
- X printf("Do you wish to continue with the undelete and overwrite that version? ");
- X if (! yes())
- X return(NO_DELETE_MASK);
- X unlink_completely(user_name);
- X }
- X if (noop) {
- X printf("%s: %s would be undeleted\n", whoami, user_name);
- X return(0);
- X }
- X
- X if (! do_file_rename(real_name, user_name)) {
- X if (verbose)
- X printf("%s: %s undeleted\n", whoami, user_name);
- X return(0);
- X }
- X else {
- X if (! force)
- X fprintf(stderr, "%s: %s not undeleted\n", whoami, user_name);
- X return(ERROR_MASK);
- X }
- X}
- X
- X
- X
- X
- Xdo_file_rename(real_name, user_name)
- Xchar *real_name, *user_name;
- X{
- X char *ptr;
- X
- X char old_name[MAXPATHLEN], new_name[MAXPATHLEN];
- X char buf[MAXPATHLEN];
- X
- X strcpy(old_name, real_name);
- X strcpy(new_name, real_name);
- X
- X while (ptr = strrindex(new_name, ".#")) {
- X convert_to_user_name(ptr, ptr);
- X strcpy(ptr, firstpart(ptr, buf));
- X strcpy(&old_name[ptr - new_name],
- X firstpart(&old_name[ptr - new_name], buf));
- X if (rename(old_name, new_name)) {
- X return(ERROR_MASK);
- X }
- X if (ptr > new_name) {
- X *--ptr = '\0';
- X old_name[ptr - new_name] = '\0';
- X }
- X }
- X change_path(real_name, user_name);
- X return(0);
- X}
- X
- X
- X
- X
- X
- X
- Xfilecmp(file1, file2)
- Xlistrec *file1, *file2;
- X{
- X return(strcmp(file1->user_name, file2->user_name));
- X}
- X
- X
- X
- Xlistrec *sort_files(data, num_data)
- Xlistrec *data;
- Xint num_data;
- X{
- X qsort(data, num_data, sizeof(listrec), filecmp);
- X return(data);
- X}
- X
- X
- X
- X
- X
- Xlistrec *unique(files, number)
- Xlistrec *files;
- Xint *number;
- X{
- X int i, last;
- X int offset;
- X
- X for (last = 0, i = 1; i < *number; i++) {
- X if (! strcmp(files[last].user_name, files[i].user_name)) {
- X int better;
- X
- X better = choose_better(files[last].real_name,
- X files[i].real_name);
- X if (better == 1) { /* the first one is better */
- X free (files[i].real_name);
- X free (files[i].user_name);
- X files[i].real_name = (char *) NULL;
- X }
- X else {
- X free (files[last].real_name);
- X free (files[last].user_name);
- X files[last].real_name = (char *) NULL;
- X last = i;
- X }
- X }
- X else
- X last = i;
- X }
- X
- X for (offset = 0, i = 0; i + offset < *number; i++) {
- X if (! files[i].real_name)
- X offset++;
- X if (i + offset < *number)
- X files[i] = files[i + offset];
- X }
- X *number -= offset;
- X files = (listrec *) realloc(files, sizeof(listrec) * *number);
- X if (! files) {
- X perror(sprintf(error_buf, "%s: unique", whoami));
- X exit(1);
- X }
- X return(files);
- X}
- X
- X
- X
- X
- Xchoose_better(str1, str2)
- Xchar *str1, *str2;
- X{
- X char *pos1, *pos2;
- X
- X pos1 = strindex(str1, ".#");
- X pos2 = strindex(str2, ".#");
- X while (pos1 && pos2) {
- X if (pos1 - str1 < pos2 - str2)
- X return(2);
- X else if (pos2 - str2 < pos1 - str1)
- X return(1);
- X pos1 = strindex(pos1 + 1, ".#");
- X pos2 = strindex(pos2 + 1, ".#");
- X }
- X if (! pos1)
- X return(1);
- X else
- X return(2);
- X}
- X
- X
- X
- X
- X
- Xunlink_completely(filename)
- Xchar *filename;
- X{
- X char buf[MAXPATHLEN];
- X struct stat stat_buf;
- X DIR *dirp;
- X struct direct *dp;
- X int status = 0;
- X
- X if (lstat(filename, &stat_buf))
- X return(1);
- X
- X if ((stat_buf.st_mode & S_IFMT) == S_IFDIR) {
- X dirp = opendir(filename);
- X if (! dirp)
- X return(1);
- X for (dp = readdir(dirp); dp != NULL; dp = readdir(dirp)) {
- X if (is_dotfile(dp->d_name))
- X continue;
- X strcpy(buf, append(filename, dp->d_name));
- X if (! buf) {
- X status = 1;
- X continue;
- X }
- X status = status | unlink_completely(buf);
- X }
- X closedir(dirp);
- X }
- X else
- X return(unlink(filename) == -1);
- X return(0);
- X}
- X
- X
- X
- X
- Xchar **get_the_files(base, reg_exp, num_found)
- Xchar *base, *reg_exp;
- Xint *num_found;
- X{
- X char **matches;
- X int num_matches;
- X char **found;
- X int num;
- X int i;
- X
- X found = (char **) malloc(0);
- X num = 0;
- X
- X matches = find_matches(base, reg_exp, &num_matches);
- X if (recursive) {
- X char **recurs_found;
- X int recurs_num;
- X
- X for (i = 0; i < num_matches; free(matches[i]), i++) {
- X if (is_deleted(lastpart(matches[i]))) {
- X found = add_str(found, num, matches[i]);
- X num++;
- X }
- X recurs_found = find_deleted_recurses(matches[i], &recurs_num);
- X add_arrays(&found, &num, &recurs_found, &recurs_num);
- X }
- X }
- X else {
- X struct stat stat_buf;
- X char **contents_found;
- X int num_contents;
- X
- X for (i = 0; i < num_matches; free(matches[i]), i++) {
- X if (is_deleted(lastpart(matches[i]))) {
- X found = add_str(found, num, matches[i]);
- X num++;
- X }
- X else if (! directoriesonly) {
- X if (lstat(matches[i], &stat_buf))
- X continue;
- X if ((stat_buf.st_mode & S_IFMT) == S_IFDIR) {
- X contents_found = find_deleted_contents(matches[i],
- X &num_contents);
- X add_arrays(&found, &num, &contents_found,
- X &num_contents);
- X }
- X }
- X }
- X
- X }
- X free(matches);
- X *num_found = num;
- X return(found);
- X}
- X
- X
- X
- X
- X
- END_OF_FILE
- if test 12143 -ne `wc -c <'undelete.c'`; then
- echo shar: \"'undelete.c'\" unpacked with wrong size!
- fi
- # end of 'undelete.c'
- fi
- echo shar: End of archive 5 \(of 6\).
- cp /dev/null ark5isdone
- MISSING=""
- for I in 1 2 3 4 5 6 ; do
- if test ! -f ark${I}isdone ; then
- MISSING="${MISSING} ${I}"
- fi
- done
- if test "${MISSING}" = "" ; then
- echo You have unpacked all 6 archives.
- rm -f ark[1-9]isdone
- else
- echo You still need to unpack the following archives:
- echo " " ${MISSING}
- fi
- ## End of shell archive.
- exit 0
-
- --
- Please send comp.sources.unix-related mail to rsalz@uunet.uu.net.
-
-
-